functor Types (S : TYPES_STRUCTS) : TYPES =
struct
  open S
  
  type id = Id.t
  
  datatype btype
    = Errt
    | NS
    | Voidt
    | Intt
    | Boolt
    | Structt of Id.t * (Id.t * btype) list
    | Arrayt of Intl.t * btype 
    | Pointt of btype
    | TypeSeq of btype * btype
    | Funct of (Id.t * btype) list * btype

  fun eq (t1, t2) =
      case (t1, t2)
       of (Intt, Intt) => true
        | (Boolt, Boolt) => true
        | (Pointt _, NS) => true
        | (NS, Pointt _) => true
        | (Structt (s1, f1), Structt (s2, f2)) => Id.equals (s1, s2)
        | _ => false
  
  fun getbasetype t =
      case t
       of Arrayt (size, bt) => bt
        | Pointt bt => bt
        | _ => t

(* false -- invalidtype true -- validtype*)  
  fun isValidtp(tp,tplist) = 
      let (*ttp -- temp type *)
	  fun check(ttp,[]) = false
	    | check(ttp,v::l) =
		 if eq (ttp, v)
		then true
		else check (ttp,l)
	  val basetype = getbasetype(tp)
      in  if check(tp,tplist)
	  then true
	  else if eq (basetype, tp)
	       then false
	       else isValidtp (basetype, tplist)
      end
    
  fun isValidrettype(tp,tlist) = isValidtp(tp,tlist) orelse eq (tp, Voidt)

  fun isPointertype ty =
      case ty
       of Pointt tp => true
        | NS => true
        | _ => false

  fun getFuncrettp(Funct(arglist,rtp)) = rtp
    | getFuncrettp(_) = Errt

  fun getArgtypes(Funct(arglist,rtp)) = 
      let fun walkon [] = []
	    | walkon((aname,atype)::l) = atype::walkon(l)
      in walkon(arglist)
      end
    | getArgtypes _ = []

  fun getFieldtype(tlist,sname,fname) =
      let fun findfield([]) = Errt
	    | findfield((tfn,ttp)::l) = 
	      if Id.equals (tfn, fname)
	      then ttp
	      else findfield(l)
      in  case tlist
	   of [] => Errt
	    | ((Structt(tsn,flist))::r) =>
	      if Id.equals (tsn, sname)
	      then findfield (flist)
	      else getFieldtype(r,sname,fname)
	    | (othertp::r) => getFieldtype(r,sname,fname)
      end

  fun Inittypelist () = [Intt, Boolt]  

end
